package com.button.boot.httpclient.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.button.boot.httpclient.service.HttpClientToolService;

@Service
public class HttpClientToolServiceImpl implements HttpClientToolService {
    private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientToolServiceImpl.class);
    private static String UTF_8 = "UTF-8";

    @Autowired
    private CloseableHttpClient httpClient;
    @Autowired
    private RequestConfig config;

    /**
     * 不带参数的get请求，如果状态码为200，则返回response，否则返回null
     * 
     * @param url
     * @return
     * @throws Exception
     */
    @Override
    public String doGet(String url) {
        CloseableHttpResponse response = null;
        try {
            // 声明 http get 请求
            HttpGet httpGet = new HttpGet(url);
            // 装载配置信息
            httpGet.setConfig(config);
            // 发起请求
            response = this.httpClient.execute(httpGet);
            // 判断状态码是否为200
            if (response.getStatusLine().getStatusCode() == 200) {
                // 返回响应体的内容
                return EntityUtils.toString(response.getEntity(), UTF_8);
            }
            LOGGER.error("http执行doGet请求返回空.url={},response={}", url, response);
            return null;
        } catch (Exception ex) {
            LOGGER.error("http执行doGet请求时异常. ex={}", ex);
            return null;
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    LOGGER.error("关闭doGet请求response时出现异常. e={}", e);
                }
            }
        }
    }

    /**
     * 带参数的get请求，如果状态码为200，则返回response，否则返回null
     * 
     * @param url
     * @return
     * @throws Exception
     */
    @Override
    public String doGet(String url, Map<String, Object> map) {
        try {
            URIBuilder uriBuilder = new URIBuilder(url);
            if (map != null) {
                // 遍历map,拼接请求参数
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
                }
            }
            // 调用不带参数的get请求
            return this.doGet(uriBuilder.build().toString());
        } catch (Exception e) {
            LOGGER.error("执行doGet请求时发生异常. e={}", e);
            return "";
        }
    }
    
    @Override
    public String doPostForm(String url) {
        return this.doPostForm(url, null);
    }
    
    @Override
    public String doPostForm(String url, Map<String, Object> map) {
        return doPostForm(url, map, null);
    }
    
    @Override
    public String doPostForm(String url, Map<String, Object> map, Map<String, String> headers) {
        CloseableHttpResponse response = null;
        try {
            // 声明httpPost请求
            HttpPost httpPost = new HttpPost(url);
            // 加入配置信息
            httpPost.setConfig(config);
            if (headers != null) {
                for (Entry<String, String> entry : headers.entrySet()) {
                    httpPost.addHeader(entry.getKey(), entry.getValue());
                }
            }
            // 判断map是否为空，不为空则进行遍历，封装from表单对象
            if (map != null) {
                List<NameValuePair> list = new ArrayList<>();
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    list.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
                }
                // 构造from表单对象
                UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(list, UTF_8);
                // 把表单放到post里
                httpPost.setEntity(urlEncodedFormEntity);
            }
            // 发起请求
            response = this.httpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == 200) {
                return EntityUtils.toString(response.getEntity(), UTF_8);
            }
            LOGGER.error("http执行doPostForm请求返回空.url={},response={}", url, response);
            return null;
        } catch (Exception ex) {
            LOGGER.error("http执行doPostForm请求时发生异常. ex={}", ex);
            return null;
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    LOGGER.error("关闭doPostForm中的response时出现异常. e={}", e);
                }
            }
        }
    }
    
    @Override
    public String doPostBody(String url, String body) {
        return doPostBody(url, body, null);
    }
    
    @Override
    public String doPostBody(String url, String body, Map<String, String> headers) {
        CloseableHttpResponse response = null;
        try {
            HttpPost httpPost = new HttpPost(url);
            httpPost.setConfig(config);
            // 判断map是否为空，不为空则进行遍历，封装from表单对象
            httpPost.addHeader("content-type", "application/json");
            if (headers != null) {
                for (Entry<String, String> entry : headers.entrySet()) {
                    httpPost.addHeader(entry.getKey(), entry.getValue());
                }
            }
            httpPost.setEntity(new StringEntity(body, "UTF-8"));
            response = this.httpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == 200) {
                return EntityUtils.toString(response.getEntity(), UTF_8);
            }
            LOGGER.error("http执行doPostBody请求返回结果为空. url={}, response={}", url, response);
            return null;
        } catch (Exception ex) {
            LOGGER.error("http执行doPostBody请求时出现异常. ex={}", ex);
            return null;
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    LOGGER.error("关闭doPostBody中的response时出现异常. e={}", e);
                }
            }
        }
    }
}
